package com.qire.manhua.view;

import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.OverScroller;

import androidx.annotation.Nullable;
import androidx.core.view.GestureDetectorCompat;
import androidx.core.view.ViewCompat;

public class ScrollLinearLayout extends LinearLayout {

    private final OverScroller mScroller;
    private final GestureDetectorCompat gestureCompat;
    private final SimpleOnGestureListener gestureListener = new SimpleOnGestureListener() {
        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            scrollBy(0, (int) distanceY);
            return true;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            fling((int) -velocityY);
            return true;
        }
    };

    public ScrollLinearLayout(Context context) {
        this(context, null);
    }

    public ScrollLinearLayout(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ScrollLinearLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public ScrollLinearLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        gestureCompat = new GestureDetectorCompat(context, gestureListener);
        mScroller = new OverScroller(context);

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return gestureCompat.onTouchEvent(event);
    }


    @Override
    public void computeScroll() {
        if (mScroller.isFinished()) {
            return;
        }

        if (mScroller.computeScrollOffset()) {
            int oldX = getScrollX();
            int oldY = getScrollY();
            int x = mScroller.getCurrX();
            int y = mScroller.getCurrY();

            if (oldX != x || oldY != y) {
                final int range = getScrollRange();
                final int overScrollMode = getOverScrollMode();
                final boolean canOverScroll = overScrollMode == OVER_SCROLL_ALWAYS ||
                        (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && range > 0);

                scrollBy(x - oldX, y - oldY);

                if (canOverScroll) {
                    if (y < 0 && oldY >= 0) {
//                        mEdgeGlowTop.onAbsorb((int) mScroller.getCurrVelocity());
                    } else if (y > range && oldY <= range) {
//                        mEdgeGlowBottom.onAbsorb((int) mScroller.getCurrVelocity());
                    }
                }
            }
        }
    }

    public void fling(int velocityY) {
        if (getChildCount() > 0) {
            mScroller.fling(getScrollX(), getScrollY(),
                    0, velocityY,
                    0, 0,
                    Integer.MIN_VALUE, Integer.MAX_VALUE,
                    0, 0);
            ViewCompat.postInvalidateOnAnimation(this);
        }
    }

    private int getScrollRange() {
        int scrollRange = 0;
        int childCount = getChildCount();
        if (childCount > 0) {
            View lastChild = getChildAt(childCount - 1);
            MarginLayoutParams lp = (MarginLayoutParams) lastChild.getLayoutParams();
            int lastBottom = lastChild.getBottom() + lp.bottomMargin;
            scrollRange = Math.max(0, lastBottom);
        }
        return scrollRange;
    }

    @Override
    public void scrollTo(int x, int y) {
        if (getChildCount() > 0) {
            View child = getChildAt(0);
            x = clamp(x, getWidth() - getPaddingRight() - getPaddingLeft(), child.getWidth());
            y = clamp(y, getHeight() - getPaddingBottom() - getPaddingTop(), getScrollRange());
            if (x != getScrollX() || y != getScrollY()) {
                super.scrollTo(x, y);
            }
        }
    }

    private static int clamp(int n, int my, int child) {
        if (my >= child || n < 0) {
            /* my >= child is this case:
             *                    |--------------- me ---------------|
             *     |------ child ------|
             * or
             *     |--------------- me ---------------|
             *            |------ child ------|
             * or
             *     |--------------- me ---------------|
             *                                  |------ child ------|
             *
             * n < 0 is this case:
             *     |------ me ------|
             *                    |-------- child --------|
             *     |-- mScrollX --|
             */
            return 0;
        }
        if ((my + n) > child) {
            /* this case:
             *                    |------ me ------|
             *     |------ child ------|
             *     |-- mScrollX --|
             */
            return child - my;
        }
        return n;
    }

}
